package com.treeengine.activity;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;

import com.treeengine.game.IGame;
import com.treeengine.game.audio.Audio;
import com.treeengine.game.audio.IAudio;
import com.treeengine.game.graphics.Graphics;
import com.treeengine.game.input.IInput;
import com.treeengine.game.input.Input;
import com.treeengine.game.io.FileIO;
import com.treeengine.game.io.IFileIO;
import com.treeengine.game.screen.Screen;

/**
 * 
 * @author himynameisgustavo@gmail.com
 */
public abstract class TreeEngine extends Activity implements Renderer{
	enum GLGameState{
		INITIALIZED,
		RUNNING,
		PAUSED,
		FINISHED,
		IDLE
	}
	
	GLSurfaceView glView;
	Graphics graphics;
	IAudio audio;
	IInput input;
	IFileIO fileIO;
	Screen screen;
	GLGameState state = GLGameState.INITIALIZED;
	Object stateChanged = new Object();
	long startTime = System.nanoTime();
	WakeLock wakeLock;
	protected boolean firstTimeCreate = true;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
							WindowManager.LayoutParams.FLAG_FULLSCREEN);
		
		glView = new GLSurfaceView(this);
		glView.setRenderer(this);
		setContentView(glView);
		
		graphics = new Graphics(glView);
		fileIO = new FileIO(this);
		audio = new Audio(this);
		input = new Input(this, glView, 1, 1);
		
		PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
		wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "TreeEngine");

	}
	
	
	@Override
	protected void onResume() {
		super.onResume();
		glView.onResume();
		wakeLock.acquire();
	}
	
	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		graphics.setGL(gl);
		
		synchronized (stateChanged) {
			if(state == GLGameState.INITIALIZED)
				screen = getStartScreen();
			state = GLGameState.RUNNING;
			screen.resume();
			startTime = System.nanoTime();
		}
	}
	
	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {}
	
	@Override
	public void onDrawFrame(GL10 gl) {
		GLGameState state = null;
		
		synchronized (stateChanged) {
			state = this.state;
		}
		
		if(state == GLGameState.RUNNING){
			float deltaTime = (System.nanoTime() - startTime) / 1000000000.0f;
			startTime = System.nanoTime();
			
			screen.update(deltaTime);
			screen.draw(deltaTime);
		}
		
		if(state == GLGameState.PAUSED){
			screen.pause();
			synchronized (stateChanged) {
				this.state = GLGameState.IDLE;
				stateChanged.notifyAll();
			}
		}
		
		if(state == GLGameState.FINISHED){
			screen.pause();
			screen.dispose();
			synchronized (stateChanged) {
				this.state = GLGameState.IDLE;
				stateChanged.notifyAll();
			}
		}
	}

	public Graphics getGraphics() {
		return graphics;
	}

	public IAudio getAudio() {
		return audio;
	}

	public IInput getInput() {
		return input;
	}

	public IFileIO getFileIO() {
		return fileIO;
	}

	public Screen getScreen() {
		return screen;
	}
	
	public abstract Screen getStartScreen();
	
	public void setScreen(Screen newScreen){
		if(screen == null)
			throw new IllegalArgumentException();
		
		screen.pause();
		screen.dispose();
		newScreen.resume();
		newScreen.update(0);
		screen = newScreen;
	}
	
	public Screen getCurrentScreen(){
		return screen;
	}
	
}
